/*************************************************
* Title：TinyToolKit
* Author：Opportunity 
* Describe：客户端消息分发处理
* CreateTime：2020-08-17 13:56:25
* Version：1.0
* Modify Recorder：
*************************************************/

using System;
using System.Collections.Generic;

namespace TinyToolKit.Network
{
    public class MsgDistribution
    {
//        public delegate void HandleProtocolCb(ProtocolBase protocol); 
        public Action<ProtocolBase> HandleProtocolCb; 
        
        private readonly int _maxHandleNum;//每帧处理消息的最大次数
        private List<ProtocolBase> _protocolList;//等待处理的消息协议列表
        private Dictionary<string,Action<ProtocolBase>> _eventDic; //消息监听表，注册一次,终身执行
        private Dictionary<string,Action<ProtocolBase>> _onceDic;//消息监听表，注册一次,执行一次

        public MsgDistribution()
        {
            _maxHandleNum = 15;
            _protocolList = new List<ProtocolBase>();
            _eventDic = new Dictionary<string, Action<ProtocolBase>>();
            _onceDic = new Dictionary<string, Action<ProtocolBase>>();
        }

        public void Update() 
        {
            //每帧最多处理_maxHandleNum条消息
            for (int i = 0; i < _maxHandleNum; i++)
            {
                lock (_protocolList)
                {
                    if (_protocolList.Count > 0)
                    {
                        DispatchMsgEvent(_protocolList[0]);
                        _protocolList.RemoveAt(0);
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
        
        public void AddProtocol(ProtocolBase protocol)
        { 
            if (protocol == null) return;
            lock (_protocolList)
            {
                _protocolList.Add(protocol);
            }
        }

        public void AddEventListener(string name,Action<ProtocolBase> cb)
        {
            if (_eventDic.ContainsKey(name))
                _eventDic[name] += cb;
            else
                _eventDic[name] = cb;
        }
        
        public void RemoveEventListener(string name,Action<ProtocolBase> cb)
        {
            if (_eventDic.ContainsKey(name))
            {
                _eventDic[name] -= cb;
                if (_eventDic[name] == null)
                    _eventDic.Remove(name);
            }
        }
        
        public void AddOnceListener(string name,Action<ProtocolBase> cb)
        {
            if (_onceDic.ContainsKey(name))
                _onceDic[name] += cb;
            else
                _onceDic[name] = cb;
        }

        public void RemoveOnceListener(string name,Action<ProtocolBase> cb)
        {
            if (_onceDic.ContainsKey(name))
            {
                _onceDic[name] -= cb;
                if (_onceDic[name] == null)
                    _onceDic.Remove(name);
            }
        }

        private void DispatchMsgEvent(ProtocolBase protocol)
        {
            string name = protocol.GetName();
            if (_eventDic.ContainsKey(name))
            {
                _eventDic[name].Invoke(protocol);
            }
            
            if (_onceDic.ContainsKey(name))
            {
                _onceDic[name].Invoke(protocol);
                _onceDic[name] = null;
                _onceDic.Remove(name);
            }
        }
    }
}
